package com.voodoo.lib_http;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.voodoo.lib_http.builder.PostFormBuilder;
import com.voodoo.lib_http.callback.FileCallBack;
import com.voodoo.lib_http.callback.StringCallback;
import com.voodoo.lib_http.https.HttpsUtils;
import com.voodoo.lib_http.logger.LoggerInterceptor;
import com.voodoo.lib_http.utils.OkHttpUtils;
import com.voodoo.lib_logcat.L;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;

/**
 * Author: voodoo
 * CreateDate: 2021/05/29
 * Description: OkHttp第二层的封装ApiTools
 * <p>
 * 使用时首先在Application的oncreate中进行初始化，调用方法：ApiTools.init();
 * 然后直接在需要请求网络数据的地方调用get()、post()等等
 */
public class ApiTools {

    private static final String TAG = "ApiTools";
    static ApiTools apiTools;
    private final Handler handler;

    private static final String RESULT_MESSAGE_KEY = "msg"; // 返回的message的key
    private static final String RESULT_CODE_KEY = "code"; // 返回的Code的key
    private static final int RESULT_SUCCESS_CODE = 0; // 返回数据正常状态

    // 第二套API返回的值
    private static boolean isSetOtherApi = false; // 是否设置了另一套Api返回值
    private static String otherResultMsgKey = "msg"; // 其他的返回的message的key
    private static String otherResultCodeKey = "code"; // 其他的返回的Code的key
    private static String otherResultSuccessCode = "0"; // 其他返回数据正常状态

    /**
     * 初始化OkHttp配置
     * 在Application的oncreate中进行初始化
     */
    static Context mContext;

    public static void init(Context context) {
        mContext = context;
        // 兼容Https的安全请求
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(null, null, null);

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout(OkHttpUtils.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
                .connectTimeout(OkHttpUtils.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
                .addInterceptor(new LoggerInterceptor("TAG")) // 日志拦截器
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager) // 设置可访问所有的https网站
                .build();

        OkHttpUtils.initClient(okHttpClient);

    }

    /**
     * 设置另外一套返回数据的Key和成功的code
     *
     * @param msgKey      消息的key
     * @param codeKey     code的key
     * @param successCode 返回成功的code
     */
    public static void setOtherApiResultData(String msgKey, String codeKey, String successCode) {
        isSetOtherApi = true;
        otherResultMsgKey = msgKey;
        otherResultCodeKey = codeKey;
        otherResultSuccessCode = successCode;
    }

    public static ApiTools getInstance() {
        if (apiTools == null) {
            synchronized (ApiTools.class) {
                if (apiTools == null) {
                    apiTools = new ApiTools();
                }
            }
        }
        return apiTools;
    }

    public ApiTools() {
        handler = new Handler(Looper.getMainLooper());
    }

    /**
     * GET请求
     *
     * @param url         请求地址
     * @param paramsMap   请求参数Map
     * @param apiListener 回调监听
     */
    public void get(final String url, Map<String, Object> paramsMap, final ApiListener apiListener) {
        L.i(TAG, "Get 请求\n请求地址：" + url + "\n请求参数：" + (paramsMap == null ? "无参" : new JSONObject(paramsMap).toString()));
        OkHttpUtils.get()
                .url(url)
                .params(paramsMap)
                .tag(url)
                .build()
                .execute(new StringCallback() {

                    /**
                     * 开始请求（数据准备和开始请求）UI线程
                     * @param request Request
                     * @param id      请求id
                     */
                    @Override
                    public void onRequestStart(Request request, int id) {
                        super.onRequestStart(request, id);
                        if (apiListener != null) {
                            apiListener.onRequestStart(url, id);
                        }
                    }

                    /**
                     * 请求完成（成功失败都会回调该方法）UI线程
                     * @param id 请求id
                     */
                    @Override
                    public void onRequestComplete(int id) {
                        super.onRequestComplete(id);
                        if (apiListener != null) {
                            apiListener.onRequestComplete(url, id);
                        }
                    }

                    /**
                     * 请求成功
                     * @param response 回传参数
                     * @param id 请求id
                     */
                    @Override
                    public void onResponse(String response, int id) {
                        L.i(TAG, "请求地址=" + url, "onResponse: " + response);
                        resultData(url, response, id, apiListener);
                    }

                    /**
                     * 请求失败
                     * @param call {@link Call}
                     * @param exception 异常信息
                     * @param id 请求id
                     */
                    @Override
                    public void onError(Call call, Exception exception, int id) {
                        L.i(TAG, "onError: " + exception.toString());
                        if (apiListener != null) {
                            resultError(url, getString(R.string.str_requestFail), exception.toString(), id, apiListener);
                        }
                    }
                });
    }

    /**
     * GET请求
     *
     * @param url         请求地址
     * @param paramsMap   请求参数Map
     * @param apiListener 回调监听
     */
    public void get(final String url, Map<String, Object> paramsMap, Map<String, String> headersMap, final ApiListener apiListener) {
        L.i(TAG, "Get 请求\n请求地址：" + url + "\n请求参数：" + (paramsMap == null ? "无参" :
                new JSONObject(paramsMap).toString()));
        OkHttpUtils.get()
                .url(url)
                .headers(headersMap)
                .params(paramsMap)
                .tag(url)
                .build()
                .execute(new StringCallback() {

                    /**
                     * 开始请求（数据准备和开始请求）UI线程
                     * @param request Request
                     * @param id      请求id
                     */
                    @Override
                    public void onRequestStart(Request request, int id) {
                        super.onRequestStart(request, id);
                        if (apiListener != null) {
                            apiListener.onRequestStart(url, id);
                        }
                    }

                    /**
                     * 请求完成（成功失败都会回调该方法）UI线程
                     * @param id 请求id
                     */
                    @Override
                    public void onRequestComplete(int id) {
                        super.onRequestComplete(id);
                        if (apiListener != null) {
                            apiListener.onRequestComplete(url, id);
                        }
                    }

                    /**
                     * 请求成功
                     * @param response 回传参数
                     * @param id 请求id
                     */
                    @Override
                    public void onResponse(String response, int id) {
                        L.i(TAG, "onResponse: " + response);
                        resultData(url, response, id, apiListener);
                    }

                    /**
                     * 请求失败
                     * @param call {@link Call}
                     * @param exception 异常信息
                     * @param id 请求id
                     */
                    @Override
                    public void onError(Call call, Exception exception, int id) {
                        L.i(TAG, "onError: " + exception.toString());
                        if (apiListener != null) {
                            resultError(url, getString(R.string.str_requestFail), exception.toString(), id, apiListener);
                        }
                    }
                });
    }

    /**
     * POST 请求
     *
     * @param url         请求地址
     * @param paramsMap   发送的数据集合
     * @param apiListener 回调监听
     */
    public void post(final String url, Map<String, Object> paramsMap, final ApiListener apiListener) {

        L.i(TAG, "Post 请求\n请求地址：" + url + "\n请求参数：" + new JSONObject(paramsMap).toString());

        PostFormBuilder post = OkHttpUtils.post();

        if (paramsMap != null && paramsMap.size() > 0) {
            for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
                if (entry.getValue() instanceof File) {
                    File file = (File) entry.getValue();
                    post.addFile(entry.getKey(), file.getName(), file);
                } else {
                    post.addParams(entry.getKey(), String.valueOf(entry.getValue()));
                }
            }
        }

        post
                .url(url)
                .tag(url)
                .build()
                .execute(new StringCallback() {
                    /**
                     * 请求之前（数据准备和开始请求）UI线程
                     * @param request Request
                     * @param id      请求id
                     */
                    @Override
                    public void onRequestStart(Request request, int id) {
                        super.onRequestStart(request, id);
                        if (apiListener != null) {
                            apiListener.onRequestStart(url, id);
                        }
                    }

                    /**
                     * 请求之后（请求完成，成功失败都会回调该方法）UI线程
                     * @param id 请求id
                     */
                    @Override
                    public void onRequestComplete(int id) {
                        super.onRequestComplete(id);
                        if (apiListener != null) {
                            apiListener.onRequestComplete(url, id);
                        }
                    }

                    /**
                     * 请求回传成功
                     * @param response 回传的JSON
                     * @param id 请求id
                     */
                    @Override
                    public void onResponse(String response, int id) {
                        L.i(TAG, "请求地址=" + url, "onResponse: " + response);
                        resultData(url, response, id, apiListener);
                    }

                    /**
                     * 请求失败
                     * @param call {@link Call}
                     * @param exception 异常信息
                     * @param id 请求id
                     */
                    @Override
                    public void onError(Call call, Exception exception, int id) {
                        L.i(TAG, "onError: " + exception.toString());
                        if (apiListener != null) {
                            resultError(url, getString(R.string.str_requestFail), exception.toString(), id, apiListener);
                        }
                    }
                });
    }

    /**
     * POST String 请求
     *
     * @param url         请求地址
     * @param jsonContent JSON字符串
     * @param apiListener 回调监听
     */
    public void post(final String url, String jsonContent, final ApiListener apiListener, String... addHeader) {
        if (url.contains("ocr_idcard")) {
            Log.i(TAG, "PostString 请求\n请求地址：" + url + "\n请求参数："
                    + "数据太长了" + "==addHeader==" + addHeader[0
                    ]);
        } else {
            Log.i(TAG, "PostString 请求\n请求地址：" + url + "\n请求参数：" +
                    jsonContent);
        }
        OkHttpUtils.postString()
                .url(url)
                .content(jsonContent)
                .tag(url).addHeader("Authorization", "APPCODE " + (addHeader.length > 0 ? addHeader[0] : ""))
                .mediaType(MediaType.parse("application/json; charset=utf-8"))
                .build()
                .execute(new StringCallback() {

                    /**
                     * 请求之前（数据准备和开始请求）UI线程
                     * @param request Request
                     * @param id      请求id
                     */
                    @Override
                    public void onRequestStart(Request request, int id) {
                        super.onRequestStart(request, id);
                        if (apiListener != null) {
                            apiListener.onRequestStart(url, id);
                        }
                    }

                    /**
                     * 请求之后（请求完成，成功失败都会回调该方法）UI线程
                     * @param id 请求id
                     */
                    @Override
                    public void onRequestComplete(int id) {
                        super.onRequestComplete(id);
                        if (apiListener != null) {
                            apiListener.onRequestComplete(url, id);
                        }
                    }

                    /**
                     * 请求成功
                     * @param response 回传的String
                     * @param id 请求id
                     */
                    @Override
                    public void onResponse(String response, int id) {
                        L.i(TAG, "请求地址=" + url, "onResponse: " + response);
                        resultData(url, response, id, apiListener);
                    }

                    /**
                     * 请求失败
                     * @param call {@link Call}
                     * @param exception 异常信息
                     * @param id 请求id
                     */
                    @Override
                    public void onError(Call call, Exception exception, int id) {
                        L.i(TAG, "onError: " + exception.toString());
                        if (apiListener != null) {
                            resultError(url, getString(R.string.str_requestFail), exception.toString(), id, apiListener);
                        }
                    }
                });
    }

    /**
     * POST String 请求
     *
     * @param url         请求地址
     * @param jsonContent JSON字符串
     * @param apiListener 回调监听
     */
    public void post(final String url, String jsonContent, Map<String, String> headersMap, final ApiListener apiListener) {
        L.i(TAG, "PostString 请求\n请求地址：" + url + "\n请求参数：" + jsonContent);
        OkHttpUtils.postString()
                .url(url)
                .headers(headersMap)
                .content(jsonContent)
                .tag(url)
                .mediaType(MediaType.parse("application/json; charset=utf-8"))
                .build()
                .execute(new StringCallback() {

                    /**
                     * 请求之前（数据准备和开始请求）UI线程
                     * @param request Request
                     * @param id      请求id
                     */
                    @Override
                    public void onRequestStart(Request request, int id) {
                        super.onRequestStart(request, id);
                        if (apiListener != null) {
                            apiListener.onRequestStart(url, id);
                        }
                    }

                    /**
                     * 请求之后（请求完成，成功失败都会回调该方法）UI线程
                     * @param id 请求id
                     */
                    @Override
                    public void onRequestComplete(int id) {
                        super.onRequestComplete(id);
                        if (apiListener != null) {
                            apiListener.onRequestComplete(url, id);
                        }
                    }

                    /**
                     * 请求成功
                     * @param response 回传的String
                     * @param id 请求id
                     */
                    @Override
                    public void onResponse(String response, int id) {
                        L.i(TAG, "请求地址=" + url, "onResponse: " + response);
                        resultData(url, response, id, apiListener);
                    }

                    /**
                     * 请求失败
                     * @param call {@link Call}
                     * @param exception 异常信息
                     * @param id 请求id
                     */
                    @Override
                    public void onError(Call call, Exception exception, int id) {
                        L.i(TAG, "onError: " + exception.toString());
                        if (apiListener != null) {
                            resultError(url, getString(R.string.str_requestFail), exception.toString(), id, apiListener);
                        }
                    }
                });
    }

    /**
     * 下载文件
     *
     * @param downloadUrl      下载地址
     * @param saveFilePath     保存的路径地址
     * @param saveFileName     保存的文件名称，连同后缀名
     * @param downloadListener 回调监听
     */
    public void download(final String downloadUrl, String saveFilePath, String saveFileName, final DownloadListener downloadListener) {
        L.i(TAG, "下载文件\n下载地址地址：" + downloadUrl + "\n保存路径：" + saveFilePath + "\n保存文件名：" + saveFileName);
        OkHttpUtils.get()
                .url(downloadUrl)
                .tag(downloadUrl)
                .build()
                .execute(new FileCallBack(saveFilePath, saveFileName) {

                    /**
                     * 开始下载
                     * @param request Request
                     * @param id      请求id
                     */
                    @Override
                    public void onRequestStart(Request request, int id) {
                        super.onRequestStart(request, id);
                        if (downloadListener != null) {
                            downloadListener.onDownloadStart(downloadUrl, id);
                        }
                    }

                    /**
                     * 下载完成（成功与失败都会调用此方法）
                     * @param id 请求id
                     */
                    @Override
                    public void onRequestComplete(int id) {
                        super.onRequestComplete(id);
                        if (downloadListener != null) {
                            downloadListener.onDownloadComplete(downloadUrl, id);
                        }
                    }

                    /**
                     * 下载中进度
                     * @param progress 当前进度百分比
                     * @param total    总进度
                     * @param id       请求id
                     */
                    @Override
                    public void onRequesting(long progress, long total, int id) {
                        super.onRequesting(progress, total, id);
                        if (downloadListener != null) {
                            downloadListener.onDownloading(downloadUrl, progress, total, id);
                        }
                    }

                    /**
                     * 下载成功
                     * @param response 下载后的文件
                     * @param id 请求id
                     */
                    @Override
                    public void onResponse(File response, int id) {
                        super.onResponse(response, id);
                        if (downloadListener != null) {
                            downloadListener.onDownloadSuccess(downloadUrl, response, id);
                        }
                    }

                    /**
                     * 下载失败
                     * @param call
                     * @param exception
                     * @param id
                     */
                    @Override
                    public void onError(Call call, Exception exception, int id) {
                        super.onError(call, exception, id);
                        if (downloadListener != null) {
                            downloadListener.onDownloadFail(downloadUrl, exception.toString(), id);
                        }
                    }

                });
    }

    /**
     * 回传消息的解析
     *
     * @param url      请求地址
     * @param response 返回的JSON数据
     * @param id       请求id
     */
    private void resultData(String url, String response, int id, ApiListener apiListener) {
        // 判断返回数据是否为空和是否是正确的JSON字符串
        if (!response.isEmpty()) {
            try {

                final JSONObject resultJson = new JSONObject(response);
                if (apiListener != null) {
                    // 先判断主Code，如果主Code是成功，那么返回成功的接口，否则的话
                    // 判断是否设置过另一套API参数，如果没设置过，则按失败处理
                    // 如果设置过，则获取并判断相应的Code，是走成功还是失败接口

                    if (url.endsWith("ocr_idcard.json")) {
                        resultSuccess(url, resultJson, id, apiListener);
                        return;
                    }
                    final int code = resultJson.optInt(RESULT_CODE_KEY, -1);
                    if (code == RESULT_SUCCESS_CODE) { // 如果返回的code和约定的正常状态的code一致则为请求成功的状态
                        resultSuccess(url, resultJson, id, apiListener);
                    } else { // 不一致的判断是否设置过第二套API值

                        // 如果不一致，则判断是都设置过第二套API返回值
                        if (isSetOtherApi) { // 设置过，就按照设置的值进行处理
                            if (otherResultSuccessCode.equals(resultJson.optString(otherResultCodeKey))) {
                                // 返回Code值和设置的成功一致，那么就是返回成功
                                resultSuccess(url, resultJson, id, apiListener);
                            } else {
                                resultError(url, resultJson.optString(otherResultMsgKey), response, id, apiListener);
                            }
                            return;
                        }

                        resultError(url, resultJson.optString(RESULT_MESSAGE_KEY), response, id, apiListener);
                    }
                }

            } catch (JSONException e) {
                if (apiListener != null) {
                    resultError(url, getString(R.string.str_resultJsonError), response, id, apiListener);
                }
            }
        } else {
            // 一般情况下不会出现该问题，因为各个厂商都会有自己的一套返回数据格式，所以很少会走这套分支
            L.e(TAG, "resultData: 返回的数据为空");
            if (apiListener != null) {
                resultError(url, getString(R.string.str_resultJsonEmpty), response, id, apiListener);
            }
        }
    }

    private void resultSuccess(final String url, final JSONObject resultJson, final int id, final ApiListener apiListener) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                apiListener.onSuccess(url, resultJson, id);
            }
        });
    }

    private void resultError(final String requestUrl, final String errorMsg, final String resultData, final int requestId, final ApiListener apiListener) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                apiListener.onError(requestUrl, errorMsg, resultData, requestId);
            }
        });
    }

    /**
     * 获取资源中的String
     *
     * @param strResId 资源id
     * @return id所对应的String
     */
    private String getString(int strResId) {
        return mContext.getResources().getString(strResId);
    }

}
